#include "stdafx.h"
#include <MyControls/Doc.h>
#include <MyControls/App.h>
#include <MyControls/Resource.h>
#include <mswin/exception.h>
#include <mswin/file_dir.h>


namespace My {

Doc::Doc() : 
	m_Actions(* this),
	m_pSelection(new NullSelection),
	m_SelectionUpdateCounter(0)
{
}

Doc::~Doc()
{
}

void Doc::Init()
{
}

void Doc::New()
{
	SetFileName(String());
}

void Doc::Open(const String & sPath, int nFilter)
{
	GetApp().BeginActivity(GetApp().LoadString(MY_ACTIVITY_OPENING));
	assert(IsEmpty());
	try {
		DoOpen(sPath, nFilter);
	} catch(...) {
		Close();
		throw;
	}
	SetFileName(sPath);
	m_Actions.Clear();
	GetApp().EndActivity();
}

bool Doc::CanClose() 
{ 
	return true; 
}

void Doc::Close()
{
	SetFileName("");
	m_Actions.Clear();
	m_Actions.NonModified();
}

void Doc::Save()
{
	SaveTo(GetFileName());
	m_Actions.NonModified();
}

void Doc::SaveAs(const String & sPath)
{
	SaveTo(sPath);
	SetFileName(sPath);
	m_Actions.NonModified();
}

void Doc::SaveTo(const String & sPath)
{
	GetApp().BeginActivity(GetApp().LoadString(MY_ACTIVITY_SAVING));
	DoSave(sPath);
	GetApp().EndActivity();
}

bool Doc::IsEmpty() const
{
	return GetFileName().empty();
}

bool Doc::IsModified() const
{
	return m_Actions.IsModified();
}

String Doc::GetFileName() const
{
	return m_FileName;
}

bool Doc::Perform(Action * pAction)
{
	return m_Actions.Perform(pAction);
}

void Doc::SetFileName(String s)
{
	if (!s.empty())
		s = mswin::fullpath(s);
	if (m_FileName != s) {
		m_FileName = s;
		DispatchEvent(FileNameChange(* this));
	}
}

Selection & Doc::GetSelection() const
{
	assert(m_pSelection);
	return * m_pSelection;
}

void Doc::SetSelection(Selection * ptr)
{
	SelectionSPtr pNew(ptr != 0 ? ptr :	new NullSelection);
	if (!pNew->Equals(* m_pSelection)) {
		m_pSelection->m_pDoc = 0;
		if (m_SelectionUpdateCounter != 0)
			m_pSelection->EndUpdate();
		m_pSelection = pNew;
		m_pSelection->m_pDoc = this;
		if (m_SelectionUpdateCounter != 0)
			m_pSelection->BeginUpdate();
		SelectionChanged();
	}
}

void Doc::SelectionChanged()
{
	DispatchEvent(SelectionChange(* this));
}

void Doc::BeginSelectionUpdate()
{
	if (m_SelectionUpdateCounter++ == 0)
		m_pSelection->BeginUpdate();
}

void Doc::EndSelectionUpdate()
{
	if (--m_SelectionUpdateCounter == 0)
		m_pSelection->EndUpdate();
}

void Doc::ProcessEvent(My::Event & e)
{
	if (e.Is<CommandEventBase>())
        GetSelection().ProcessEvent(e);
}

// SelectionUpdate

SelectionUpdate::SelectionUpdate()
{
	GetApp().GetDoc().BeginSelectionUpdate();
}

SelectionUpdate::~SelectionUpdate()
{
	GetApp().GetDoc().EndSelectionUpdate();
}

// Selection

Selection::Selection() : 
	m_pDoc(0)
{
}

Selection::~Selection()
{
}

void Selection::Changed()
{
	if (m_pDoc != 0 && !m_pDoc->IsEmpty())
		m_pDoc->SelectionChanged();
}

Selection & GetSelection()
{
	return GetApp().GetDoc().GetSelection();
}

void SetSelection(Selection * ptr)
{
	GetApp().GetDoc().SetSelection(ptr);
}

bool Perform(Action * pAction)
{
	return GetApp().GetDoc().Perform(pAction);
}


} // My